from drf_spectacular.utils import extend_schema_field
from rest_framework import serializers

from common.serializer import (
    AttachmentsSerializer,
    CommentSerializer,
    ProfileSerializer,
    TagsSerializer,
    TeamsSerializer,
    UserSerializer,
)
from contacts.serializer import ContactSerializer
from tasks.models import Board, BoardColumn, BoardMember, BoardTask, Task


class BoardMemberSerializer(serializers.ModelSerializer):
    """Serializer for board members"""

    profile = ProfileSerializer(read_only=True)
    profile_id = serializers.UUIDField(write_only=True, required=False)

    class Meta:
        model = BoardMember
        fields = "__all__"
        read_only_fields = ("id", "created_at", "updated_at", "board")


class BoardTaskSerializer(serializers.ModelSerializer):
    """Serializer for board tasks"""

    assigned_to = ProfileSerializer(many=True, read_only=True)
    assigned_to_ids = serializers.ListField(
        child=serializers.UUIDField(), write_only=True, required=False
    )
    is_completed = serializers.BooleanField(read_only=True)
    is_overdue = serializers.BooleanField(read_only=True)

    class Meta:
        model = BoardTask
        fields = "__all__"
        read_only_fields = ("id", "created_at", "updated_at", "completed_at")


class BoardColumnSerializer(serializers.ModelSerializer):
    """Serializer for board columns"""

    tasks = BoardTaskSerializer(many=True, read_only=True)
    task_count = serializers.SerializerMethodField()

    class Meta:
        model = BoardColumn
        fields = "__all__"
        read_only_fields = ("id", "created_at", "updated_at", "board")

    @extend_schema_field(int)
    def get_task_count(self, obj):
        return obj.tasks.count()


class BoardColumnListSerializer(serializers.ModelSerializer):
    """Simplified column serializer for lists"""

    task_count = serializers.SerializerMethodField()

    class Meta:
        model = BoardColumn
        fields = ["id", "name", "order", "color", "limit", "task_count"]

    @extend_schema_field(int)
    def get_task_count(self, obj):
        return obj.tasks.count()


class BoardSerializer(serializers.ModelSerializer):
    """Serializer for boards"""

    owner = ProfileSerializer(read_only=True)
    columns = BoardColumnListSerializer(many=True, read_only=True)
    members = BoardMemberSerializer(source="memberships", many=True, read_only=True)
    member_count = serializers.SerializerMethodField()
    task_count = serializers.SerializerMethodField()

    class Meta:
        model = Board
        fields = "__all__"
        read_only_fields = (
            "id",
            "created_at",
            "updated_at",
            "created_by",
            "updated_by",
            "owner",
            "org",
        )

    @extend_schema_field(int)
    def get_member_count(self, obj):
        return obj.members.count()

    @extend_schema_field(int)
    def get_task_count(self, obj):
        return BoardTask.objects.filter(column__board=obj).count()


class BoardListSerializer(serializers.ModelSerializer):
    """Simplified board serializer for lists"""

    owner = ProfileSerializer(read_only=True)
    member_count = serializers.SerializerMethodField()
    column_count = serializers.SerializerMethodField()
    task_count = serializers.SerializerMethodField()

    class Meta:
        model = Board
        fields = [
            "id",
            "name",
            "description",
            "owner",
            "is_archived",
            "member_count",
            "column_count",
            "task_count",
            "created_at",
            "updated_at",
        ]

    @extend_schema_field(int)
    def get_member_count(self, obj):
        return obj.members.count()

    @extend_schema_field(int)
    def get_column_count(self, obj):
        return obj.columns.count()

    @extend_schema_field(int)
    def get_task_count(self, obj):
        return BoardTask.objects.filter(column__board=obj).count()


class TaskSerializer(serializers.ModelSerializer):
    created_by = UserSerializer()
    assigned_to = ProfileSerializer(read_only=True, many=True)
    contacts = ContactSerializer(read_only=True, many=True)
    teams = TeamsSerializer(read_only=True, many=True)
    tags = TagsSerializer(read_only=True, many=True)
    task_attachment = AttachmentsSerializer(read_only=True, many=True)
    task_comments = CommentSerializer(read_only=True, many=True)

    class Meta:
        model = Task
        fields = (
            "id",
            "title",
            "status",
            "priority",
            "due_date",
            "description",
            "account",
            "opportunity",
            "case",
            "lead",
            "created_by",
            "created_at",
            "contacts",
            "teams",
            "assigned_to",
            "tags",
            "task_attachment",
            "task_comments",
        )


class TaskCreateSerializer(serializers.ModelSerializer):
    def __init__(self, *args, **kwargs):
        request_obj = kwargs.pop("request_obj", None)
        super().__init__(*args, **kwargs)
        self.org = request_obj.profile.org

        self.fields["title"].required = True

    def validate_title(self, title):
        if self.instance:
            if (
                Task.objects.filter(title__iexact=title, org=self.org)
                .exclude(id=self.instance.id)
                .exists()
            ):
                raise serializers.ValidationError("Task already exists with this title")
        else:
            if Task.objects.filter(title__iexact=title, org=self.org).exists():
                raise serializers.ValidationError("Task already exists with this title")
        return title

    def validate(self, attrs):
        """Validate that task has at most one parent entity."""
        attrs = super().validate(attrs)
        parent_fields = ["account", "opportunity", "case", "lead"]
        set_parents = [field for field in parent_fields if attrs.get(field)]
        if len(set_parents) > 1:
            raise serializers.ValidationError(
                {
                    "account": (
                        "A task can only be linked to one parent entity "
                        f"(Account, Opportunity, Case, or Lead). "
                        f"Currently set: {', '.join(set_parents)}"
                    )
                }
            )
        return attrs

    class Meta:
        model = Task
        fields = (
            "id",
            "title",
            "status",
            "priority",
            "due_date",
            "description",
            "account",
            "opportunity",
            "case",
            "lead",
            "created_by",
            "created_at",
        )


class TaskDetailEditSwaggerSerializer(serializers.Serializer):
    comment = serializers.CharField()
    task_attachment = serializers.FileField()


class TaskCommentEditSwaggerSerializer(serializers.Serializer):
    comment = serializers.CharField()


class TaskCreateSwaggerSerializer(serializers.ModelSerializer):
    class Meta:
        model = Task
        fields = (
            "title",
            "status",
            "priority",
            "due_date",
            "description",
            "account",
            "opportunity",
            "case",
            "lead",
            "contacts",
            "teams",
            "assigned_to",
            "tags",
        )
